/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "AliasList.h"
#include "Words.h"
#include "myassert.h"
#include "Table.h"
#include "StringBuilder.h"
#include "config.h"

#include <string.h>
#include <stdlib.h>

using namespace Chronos;
using namespace std;

static const char* DELIMITER = "\n";

AliasList::AliasList(const string& init)
	: notFound("")
{
    if (init != "") {
        char buf[init.length()+1];
        strcpy(buf, init.c_str());
        char* left = strtok(buf, DELIMITER); 
        while (left != 0) {
            char* right = strtok(0, DELIMITER);
            ASSERT_NOT_NULL(right);
            add(left, right);
            left = strtok(0, DELIMITER); 
        }
    }
}


void AliasList::add(const string& key, const string& value) {
	aliases[key] = value;
}


bool AliasList::remove(const string& key) {
	AliasesIter iter = aliases.find(key);
	if (iter == aliases.end()) return false;
	aliases.erase(iter);
	return true;
}


const string& AliasList::find(const string& key) const {
	AliasesConstIter iter = aliases.find(key);
	if (iter != aliases.end()) return iter->second;
	return notFound;
}


int AliasList::size() const { return aliases.size(); }


string AliasList::replace(const string& input) const {
    Words words(input);
    if (words.getCount() == 0) return input;
    if (words[0] == "alias" || words[0] == "unalias") return input;
    StringBuilder buffer;
    for (int i=0; i<words.getCount(); ++i) {
        string alias = find(words[i]);
        if (i != 0) buffer << ' ';
        if (alias == "") buffer << words[i]; 
        else buffer << alias;
    }
    return string(buffer);
}


string AliasList::toString() const {
    StringBuilder buffer;
	for (AliasesConstIter iter = aliases.begin(); iter != aliases.end(); ++iter) {
        if (!buffer.isEmpty()) buffer << DELIMITER;
        buffer << iter->first << DELIMITER << iter->second;
    }
    return string(buffer);
}


void AliasList::printAliases(StringBuilder& buffer) {
    static const char* arrow = "->";
    buffer << "aliases: (" << size() << '/' << Config::MAX_ALIASES << ")\n";
    Table table(3);
    table.setMargin(3);
	for (AliasesConstIter iter = aliases.begin(); iter != aliases.end(); ++iter) {
        table.addCell(iter->first);
        table.addCell(arrow);
        table.addCell(iter->second);
    }
    table.write(buffer);
}

